document.addEventListener("DOMContentLoaded", () => {
    const $sct = document.querySelector(".shape_controls");
    const $srt = document.querySelector(".shape_controls .shape_rotater");
    const {left, top, width, height} = $sct.getBoundingClientRect();
    // 原点坐标
    const origin = [left + width / 2 , top + height / 2];
    // 是否旋转中
    let rotating = false;
    // 旋转矩阵
    let prevRotateMatrix = getElementTranformMatrix($sct);
    let aVector = null;
    let bVector = null;

    /**
     * 获取元素的变换矩阵
     * @param {HTMLElement} el 元素对象
     * @returns {Array.<16>} 
     */
    function getElementTranformMatrix(el) {
        const matrix = getComputedStyle(el)
                        .transform
                        .replace("matrix(", "")
                        .replace(")", "")
                        .split(",")
                        .map(item => parseFloat(item.trim()));
        return new Float32Array([
            matrix[0], matrix[2], 0, 0,
            matrix[1], matrix[3], 0, 0,
            0, 0, 1, 0,
            matrix[4], matrix[5], 0, 1
        ]);
    }

    /**
     * 给元素设置变换矩阵
     * @param {HTMLElement} el 元素对象
     * @param {Array.<16>} hcm 齐次坐标4x4矩阵 
     */
    function setElementTranformMatrix(el, hcm) {
        el.setAttribute("style", `transform: matrix(${hcm[0]} ,${hcm[4]}, ${hcm[1]}, ${hcm[5]}, ${hcm[12]}, ${hcm[13]});`);
    }

    /**
     * 计算向量夹角，单位是弧度
     * @param {Array.<2>} av 
     * @param {Array.<2>} bv 
     * @returns {number}
     */
    function computedIncludedAngle(av, bv) {
        return Math.atan2(av[1], av[0]) - Math.atan2(bv[1], bv[0]);
    }

    // 监听元素的点击事件，如果点击了旋转圆圈，开始设置起始旋转向量
    $srt.addEventListener("mousedown", (e) => {
        const {clientX, clientY} = e;
        rotating = true;
        aVector = [clientX - origin[0], clientY - origin[1]];
    });

    // 监听页面鼠标移动事件，如果处于旋转状态中，就计算出旋转矩阵，重新渲染
    document.addEventListener("mousemove", (e) => {
        // 如果不处于旋转状态，直接返回，避免不必要的无意义渲染
        if (!rotating) {
            return;
        }
        // 计算出当前坐标点与原点之间的向量
        const {clientX, clientY} = e;
        bVector = [clientX - origin[0], clientY - origin[1]];
        // 根据2个向量计算出旋转的弧度
        const angle  = computedIncludedAngle(aVector, bVector);

        const o = new Float32Array([
            0, 0, 0, 0,
            0, 0, 0, 0,
            0, 0, 0, 0,
            0, 0, 0, 0
        ]);
        // 旋转矩阵
        const rotateMatrix = new Float32Array([
            Math.cos(angle), Math.sin(angle), 0, 0,
            -Math.sin(angle), Math.cos(angle), 0, 0,
            0, 0, 1, 0,
            0, 0, 0, 1
        ]);
        // 把当前渲染矩阵根据旋转矩阵，进行矩阵变换，得到新矩阵
        prevRotateMatrix = glMatrix.mat4.multiply(o, prevRotateMatrix, rotateMatrix); 
        // 给元素设置变换矩阵，完成旋转
        setElementTranformMatrix($sct, prevRotateMatrix);
        aVector = bVector;
    });

    // 鼠标弹起后，移除旋转状态
    document.addEventListener("mouseup", () => {
        rotating = false;
    })    
});